#include <SDL/SDL.h>
#include <SDL/sge_primitives.h>
#include <iostream>
#include <map>
#include <sstream>
#include <stdexcept>

// 0 — black 0 0 0 8 — orange 0.375 -0.707 0.707
// 1 — white 1 0 0 9 — brown 0.25 -0.924 0.383
// 2 — red 0.313 -0.383 0.924 10 — light red 0.5 -0.383 0.924
// 3 — cyan 0.625 0.383 -0.924 11 — dark grey 0.313 0 0
// 4 — purple 0.375 0.707 0.707 12 — grey 0.469 0 0
// 5 — green 0.5 -0.707 -0.707 13 — light green 0.75 -0.707
// 6 — blue 0.25 1 0 14 — light blue 0.469 1 0
// 7 — yellow 0.75 -1 0 15 — light grey 0.625 0 

Uint32 default_colours[] = {
  0x000000, //black
  0xFFFFFF, //white
  0x883932, //red
  0x67B6BD, //cyan
  0x8B3F96, //purple
  0x55A049, //green
  0x40318D, //blue
  0xBFCE72, //yellow
  0x8B5429, //orange
  0x574200, //brown
  0xB86962, //light red
  0x505050, //dark gray
  0x787878, //gray
  0x9F9F9F, //light green
  0x94E089, //light blue
  0x7869C4, //light grey
  0xEAB489, //light orange
  0xC7FFFF, //light cyan
  0xEA9FF6, //light magenta
  0xFFFFB2, //light yellow
};

using namespace std;

SDL_Surface *screen;

struct Context {
  SDL_Surface *surface;
  Uint32 fgcol;
  Uint32 bgcol;
};

/*! \brief do a single command.
 *
 * Do a single painting command.
 *
 * \param cmd command in text form
 * \param ctx painting context
 * \return 1=OK, 0=ERROR, -1=quit 
 */
short do_command(const string& line, Context *ctx) {
  string cmd;
  Sint16 x1, y1, x2, y2;
  istringstream in(line);
  
  if(!(in >> cmd)) return -1;
  if(cmd == "quit") {
    return -1;
  } else if(cmd == "clear") {
    sge_FilledRect(screen, 0, 0, ctx->surface->w - 1, ctx->surface->h - 1, ctx->bgcol);
    return 1;    
  } else if(cmd == "line") {
    if(in >> x1 >> y1 >> x2 >> y2) {
      sge_Line(screen, x1, y1, x2, y2, ctx->fgcol);
      return 1;
    }
  } else if(cmd == "col") {
    if(in >> x1) {
      ctx->fgcol = default_colours[x1];
      return 1;
    }
  } else if(cmd == "rect") {
    if(in >> x1 >> y1 >> x2 >> y2) {
      sge_Rect(screen, x1, y1, x2, y2, ctx->fgcol);
      return 1;
    }
  } else if(cmd == "frect") {
    if(in >> x1 >> y1 >> x2 >> y2) {
      sge_FilledRect(screen, x1, y1, x2, y2, ctx->fgcol);
      return 1;
    }
  }
  return 0;
}

int main() {
  Uint32 bgcol;
  Uint32 fgcol;
  string line;

  if(SDL_Init(SDL_INIT_VIDEO) == 0) {
    atexit(SDL_Quit);
    screen = SDL_SetVideoMode(800, 600, 32, SDL_DOUBLEBUF | SDL_HWSURFACE);
    if(screen != NULL) {
      Context context = {
	screen,
	0x7869c4, //Foreground, SDL_MapRGB(screen->format, 0x78, 0x69, 0xc4);
	SDL_MapRGB(screen->format, 0x40, 0x31, 0x8d)
      };
      bool quit = false;
      SDL_FillRect(screen, NULL, context.bgcol);
      SDL_Flip(screen);
      while(!quit && getline(cin, line)) {
	switch(do_command(line, &context)) {
	case 0:
	  cout << "ERROR!\n";
	  break;
	case 1:
	  cout << "OK!\n";
	  break;
	case -1:
	  quit = true;
	  break;
	default:
	  throw runtime_error("invalid do_command()");
	}
	SDL_Flip(screen);
      }
      //SDL_Delay(2000);
    }
  }
  return 0;
}
